#include"process.h"
#include<stdlib.h>
#include<time.h>

int procInit(Process* the_proc, ProcessType the_type ,Instruction* insts, int insts_size, PROC_PRIORITY the_priority){
  int rv = 0;

  the_proc->PC = 0;
  the_proc->inst_size = insts_size;
  the_proc->s = RUNNABLE;
  the_proc->t = the_type;
  the_proc->instructions = insts;
  the_proc->priority = the_priority;
  return rv;
}

Instruction procNextInstruction(Process* the_proc){
  Instruction i;
  i = the_proc->instructions[the_proc->PC];

  the_proc->PC = (the_proc->PC + 1) % the_proc->inst_size;

  return i;
}

Process* createUI(){
  Process* new_proc;
  Instruction* insts;
  Instruction temp;
  int i = 0;
  int r_i = 0;

  srand(time(NULL));

  insts = (Instruction*)malloc(sizeof(Instruction) * 30);
  for(i=0;i<30;i++){
    temp.type = DUMB_INST;
    temp.arg = 0;
    insts[i] = temp;
  }

  for(i=0;i<4;i++){
    temp.type = IO_REQ;
    temp.arg = KEYBOARD;
    r_i = rand() % 30;
    insts[r_i] = temp;
  }

  for(i=0;i<2;i++){
    temp.type = IO_REQ;
    temp.arg = JOYSTICK;
    r_i = rand() % 30;
    insts[r_i] = temp;
  }

  //randome requests for OS memory 0-3
  temp.type = MEM_UP;
  temp.arg = 0;
  r_i = rand() % 30;
  insts[r_i] = temp;

  temp.type = MEM_UP;
  temp.arg = 1;
  r_i = rand() % 30;
  insts[r_i] = temp;

  temp.type = MEM_UP;
  temp.arg = 2;
  r_i = rand() % 30;
  insts[r_i] = temp;

  temp.type = MEM_UP;
  temp.arg = 3;
  r_i = rand() % 30;
  insts[r_i] = temp;

  new_proc =(Process*)malloc(sizeof(Process));
  procInit(new_proc, UI, insts, 30, PRIORITY_VERY_HIGH);

  return new_proc;
}
Process* createCalc(){
  Process* new_proc;
  Instruction* insts;
  Instruction temp;
  int i = 0;
  int r_i = 0;

  srand(time(NULL));

  insts = (Instruction*)malloc(sizeof(Instruction) * 30);
  for(i=0;i<30;i++){
    temp.type = DUMB_INST;
    temp.arg = 0;
    insts[i] = temp;
  }

  for(i=0;i<4;i++){
    temp.type = IO_REQ;
    temp.arg = KEYBOARD;
    r_i = rand() % 30;
    insts[r_i] = temp;
  }

  //randome requests for CALC memory 4-7
  temp.type = MEM_UP;
  temp.arg = 4;
  r_i = rand() % 30;
  insts[r_i] = temp;

  temp.type = MEM_UP;
  temp.arg = 5;
  r_i = rand() % 30;
  insts[r_i] = temp;

  temp.type = MEM_UP;
  temp.arg = 6;
  r_i = rand() % 30;
  insts[r_i] = temp;

  temp.type = MEM_UP;
  temp.arg = 7;
  r_i = rand() % 30;
  insts[r_i] = temp;

  new_proc =(Process*)malloc(sizeof(Process));
  procInit(new_proc, CALC, insts, 30, PRIORITY_LOW);
  return new_proc;
}
Process* createProd(int mem_addr){
  Process* new_proc;
  Instruction* insts;
  Instruction temp;
  int i = 0;
  int r_i = 0;

  srand(time(NULL));

  insts = (Instruction*)malloc(sizeof(Instruction) *30);
  for(i=0;i<30;i++){
    temp.type = DUMB_INST;
    temp.arg = 0;
    insts[i] = temp;
  }

  for(i=0;i<10;i++){
    temp.type = MEM_UP;
    temp.arg = mem_addr;
    r_i = rand() % 30;
    insts[r_i] = temp;
  }

  new_proc =(Process*)malloc(sizeof(Process));
  procInit(new_proc, PROD, insts, 30, PRIORITY_LOW);

  return new_proc;
}
Process* createCons(int mem_addr){
  Process* new_proc;
  Instruction* insts;
  Instruction temp;
  int i = 0;
  int r_i = 0;

  srand(time(NULL));

  insts = (Instruction*)malloc(sizeof(Instruction) *30);
  for(i=0;i<30;i++){
    temp.type = DUMB_INST;
    temp.arg = 0;
    insts[i] = temp;
  }

  for(i=0;i<10;i++){
    temp.type = MEM_DN;
    temp.arg = mem_addr;
    r_i = rand() % 30;
    insts[r_i] = temp;
  }

  new_proc =(Process*)malloc(sizeof(Process));
  procInit(new_proc, CONS, insts, 30, PRIORITY_AVG);

  return new_proc;
}

char* procStateToString(ProcessState the_state){
  char* message;

  switch(the_state){
  case RUNNING:
    message = malloc(8);
    message = "Running";
    break;
  case BLOCKED:
    message = malloc(8);
    message = "Blocked";
    break;
  case RUNNABLE:
    message = malloc(9);
    message = "Runnable";
    break;
  }
  return message;
}
char* procTypeToString(ProcessType the_type){
  char * message;

    switch(the_type){
    case UI:
      message = malloc(3);
      message = "UI";
      break;
    case CALC:
      message = malloc(5);
      message = "CALC";
      break;
    case PROD:
      message = malloc(5);
      message = "PROD";
      break;
    case CONS:
      message = malloc(5);
      message = "Cons";
      break;
    }
    return message;
}
